package com.codeoss.framework.view.pagebean.crud;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.codeoss.framework.context.YunContext;
import com.codeoss.framework.data.metadata.Query;
import com.codeoss.framework.data.metadata.Restrictions;
import com.codeoss.framework.data.metadata.Table;
import com.codeoss.framework.data.metadata.TableData;
import com.codeoss.framework.data.store.ITableStore;
import com.codeoss.framework.view.component.IDataBindSource;
import com.codeoss.framework.view.component.IDataBinding;
import com.codeoss.framework.view.component.Page;
import com.codeoss.framework.view.datasource.DataSourceConfig;
import com.codeoss.framework.view.datasource.IDataSource;
import com.codeoss.framework.view.datasource.store.IDataSourceStore;

@Service
public class PageBeanCRUDUtil {
	@Autowired
	private IDataSourceStore dataSourceStore;
	@Autowired
	private ITableStore tableStore;

	public SelectResponse select(YunContext yunContext, SelectRequest selectRequest) {
		SelectResponse selectResponse = new SelectResponse();
		Table mainTable = selectRequest.getMainTable();
		IDataSource dataSource = dataSourceStore.getDataSource(mainTable.getAccessType());
		Query mainQuery = selectRequest.getMainQuery();
		TableData tableData = dataSource.select(yunContext, mainTable, mainQuery);
		selectResponse.addTableData(mainTable.getTableName(), tableData);
		if (tableData.getData().size() > 0) {
			if (selectRequest.isBatchSelect()) {
				Map<String, Object> dataMap = tableData.getData().get(0);
				for (int i = 0; i < selectRequest.getSubTableList().size(); i++) {
					Table subTable = selectRequest.getSubTableList().get(i);
					List<Map<String, Object>> subDataList = (List<Map<String, Object>>) dataMap.remove(subTable.getTableName());
					if (subDataList == null) {
						subDataList = new ArrayList<Map<String, Object>>();
					}
					TableData subTableData = new TableData();
					subTableData.setData(subDataList);
					subTableData.setTotal(subDataList.size());
					selectResponse.addTableData(subTable.getTableName(), subTableData);
				}
			} else {
				Map<String, Object> dataMap = tableData.getData().get(0);
				Object parentValue=dataMap.get(mainTable.getPrimaryKeyColumn().getColumnName());
				for (int i = 0; i < selectRequest.getSubTableList().size(); i++) {
					Table subTable = selectRequest.getSubTableList().get(i);
					Query subQuery=selectRequest.getSubQueryMap().get(subTable.getTableName());
					subQuery.add(Restrictions.eq(subTable.getParentColumn().getColumnName(), parentValue));
					IDataSource subDataSource = dataSourceStore.getDataSource(subTable.getAccessType());
					TableData subTableData = subDataSource.select(yunContext, subTable,subQuery);
					selectResponse.addTableData(subTable.getTableName(), subTableData);
				}
			}
		}
		return selectResponse;
	}

	public DeleteResponse delete(YunContext yunContext, DeleteRequest deleteRequest) {
		DeleteResponse deleteResponse = new DeleteResponse();
		Table table = deleteRequest.getTable();
		IDataSource dataSource = dataSourceStore.getDataSource(table.getAccessType());
		dataSource.delete(yunContext, table, deleteRequest.getDataMap());
		return deleteResponse;
	}

	public InsertResponse insert(YunContext yunContext, InsertRequest insertRequest) {
		InsertResponse insertResponse = new InsertResponse();
		Table mainTable = insertRequest.getMainTable();
		IDataSource dataSource = dataSourceStore.getDataSource(mainTable.getAccessType());
		if(insertRequest.isBatchSave()) {
			Map<String,Object> mainDataMap=insertRequest.getMainDataMap();
			List<Table> tableList=insertRequest.getSubTableList();
			for (int i=0;i<tableList.size();i++) {
				Table subTable = tableList.get(i);
				mainDataMap.put(subTable.getTableName(), insertRequest.getSubDataMap().get(subTable.getTableName()));
			}
			dataSource.insert(yunContext, mainTable,mainDataMap);
		}else {
			Map<String,Object> mainDataMap=insertRequest.getMainDataMap();
			dataSource.insert(yunContext, mainTable, mainDataMap);
			Object keyValue=mainDataMap.get(mainTable.getPrimaryKeyColumn().getColumnName());
			List<Table> tableList=insertRequest.getSubTableList();
			for (int i=0;i<tableList.size();i++) {
				Table subTable = tableList.get(i);
				IDataSource subDataSource = dataSourceStore.getDataSource(subTable.getAccessType());
				List<Map<String,Object>> dataList=insertRequest.getSubDataMap().get(subTable.getTableName());
				if(dataList!=null && dataList.size()>0) {
					for(int j=0;j<dataList.size();j++) {
						Map<String,Object> dataMap=dataList.get(j);
						dataMap.put(subTable.getParentColumn().getColumnName(), keyValue);
						dataMap.remove("_recordState_");
						subDataSource.insert(yunContext, subTable,dataMap);
					}
				}
			}
		}
		Map<String,Object> mainDataMap=insertRequest.getMainDataMap();
		Object keyValue=mainDataMap.get(mainTable.getPrimaryKeyColumn().getColumnName());
		insertResponse.setKeyValue(keyValue);
		return insertResponse;
	}
	
	public UpdateResponse update(YunContext yunContext, UpdateRequest updateRequest) {
		UpdateResponse updateResponse = new UpdateResponse();
		Table mainTable = updateRequest.getMainTable();
		IDataSource dataSource = dataSourceStore.getDataSource(mainTable.getAccessType());
		if(updateRequest.isBatchSave()) {
			Map<String,Object> mainDataMap=updateRequest.getMainDataMap();
			List<Table> tableList=updateRequest.getSubTableList();
			for (int i=0;i<tableList.size();i++) {
				Table subTable = tableList.get(i);
				mainDataMap.put(subTable.getTableName(), updateRequest.getSubDataMap().get(subTable.getTableName()));
			}
			dataSource.update(yunContext, mainTable,mainDataMap);
		}else {
			Map<String,Object> mainDataMap=updateRequest.getMainDataMap();
			dataSource.update(yunContext, mainTable, mainDataMap);
			Object keyValue=mainDataMap.get(mainTable.getPrimaryKeyColumn().getColumnName());
			List<Table> tableList=updateRequest.getSubTableList();
			for (int i=0;i<tableList.size();i++) {
				Table subTable = tableList.get(i);
				IDataSource subDataSource = dataSourceStore.getDataSource(subTable.getAccessType());
				List<Map<String,Object>> dataList=updateRequest.getSubDataMap().get(subTable.getTableName());
				if(dataList!=null && dataList.size()>0) {
					for(int j=0;j<dataList.size();j++) {
						Map<String,Object> dataMap=dataList.get(j);
						dataMap.put(subTable.getParentColumn().getColumnName(), keyValue);
						dataMap.remove("_recordState_");
						if (dataMap.get(subTable.getPrimaryKeyColumn().getColumnName()) == null) {
							subDataSource.insert(yunContext, subTable, dataMap);
						}else {
							subDataSource.update(yunContext, subTable,dataMap);
						}
					}
				}
			}
		}
		return updateResponse;
	}
	
	public TableData getTableData(YunContext yunContext, Page page,
			com.codeoss.framework.view.component.Table tableComponent, Query query) {
		DataSourceConfig dataSourceConfig = page.getDataSourceConfigById(tableComponent.getDataSource());
		Table table = tableStore.get(dataSourceConfig.getTableName());
		SelectRequest queryRequest = new SelectRequest();
		queryRequest.setMainTable(table);
		queryRequest.setMainQuery(query);
		SelectResponse queryResponse = select(yunContext, queryRequest);
		TableData tableData = queryResponse.getTableDataMap().get(table.getTableName());
		return tableData;
	}

	public DeleteResponse deleteTableData(YunContext yunContext, Page page,
			com.codeoss.framework.view.component.Table tableComponent, Map<String, Object> dataMap) {
		DataSourceConfig dataSourceConfig = page.getDataSourceConfigById(tableComponent.getDataSource());
		Table table = tableStore.get(dataSourceConfig.getTableName());
		DeleteRequest deleteRequest = new DeleteRequest();
		deleteRequest.setTable(table);
		deleteRequest.setDataMap(dataMap);
		return delete(yunContext, deleteRequest);
	}
	
	public DeleteResponse deleteFormData(YunContext yunContext, Page page,
			List<IDataBinding> formDataBindingList , Map<String, Object> dataMap) {
		DataSourceConfig dataSourceConfig = page.getDataSourceConfigById(((IDataBindSource)formDataBindingList.get(0)).getDataSource());
		Table table = tableStore.get(dataSourceConfig.getTableName());
		DeleteRequest deleteRequest = new DeleteRequest();
		deleteRequest.setTable(table);
		deleteRequest.setDataMap(dataMap);
		return delete(yunContext, deleteRequest);
	}
}
